package com.molichuxing.services.infrastructure.service.impl;

import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.services.infrastructure.bean.InvoiceBean;
import com.molichuxing.services.infrastructure.convertor.Convert;
import com.molichuxing.services.infrastructure.dao.InvoiceMapper;
import com.molichuxing.services.infrastructure.dto.request.create.InvoiceCreateDto;
import com.molichuxing.services.infrastructure.dto.request.modify.InvoiceDto;
import com.molichuxing.services.infrastructure.service.InvoiceService;
import com.molichuxing.services.property.InvoiceBusinessTypeEnum;
import com.molichuxing.services.property.InvoiceStatusEnum;
import com.molichuxing.services.property.InvoiceTypeEnum;
import com.molichuxing.services.property.IsDeleteEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * <p>
 * 发票 服务实现类
 * </p>
 *
 * @author zhaopenghui
 * @since 2019-09-24
 */
@Service("invoiceService")
public class InvoiceServiceImpl implements InvoiceService {

    @Autowired
    InvoiceMapper invoiceMapper;

    /**
     * 发票创建
     *
     * @param invoiceCreateDto
     * @return
     * @throws Exception
     */
    @Override
    public Boolean createInvoice(InvoiceCreateDto invoiceCreateDto) throws Exception {
        Assert.notNull(invoiceCreateDto, "发票创建失败");

        InvoiceBean invoiceBean = Convert.toInvoiceBean(invoiceCreateDto);
        modifyInvoiceBean(invoiceCreateDto, invoiceBean);
        int result = invoiceMapper.create(invoiceBean);
        if (result > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 发票批量创建
     *
     * @param list
     * @return
     * @throws Exception
     */
    @Override
    public Boolean createInvoiceList(List<InvoiceCreateDto> list) throws Exception {
        if (null == list || list.size() < 1) {
            throw new BizException("发票创建失败");
        }

        List<InvoiceBean> invoiceBeanList = new ArrayList<>();
        for (InvoiceCreateDto invoiceCreateDto : list) {
            InvoiceBean invoiceBean = Convert.toInvoiceBean(invoiceCreateDto);
            modifyInvoiceBean(invoiceCreateDto, invoiceBean);
            invoiceBeanList.add(invoiceBean);
        }

        int result = invoiceMapper.createBatch(invoiceBeanList);
        if (result != invoiceBeanList.size()) {
            return false;
        }
        return true;
    }


    /**
     * 修改发票bean
     *
     * @param invoiceCreateDto
     * @param invoiceBean
     * @throws Exception
     */
    private void modifyInvoiceBean(InvoiceCreateDto invoiceCreateDto, InvoiceBean invoiceBean) throws Exception {
        Integer businessType = invoiceCreateDto.getBusinessType();
        Integer type = invoiceCreateDto.getType();
        Integer currentPeriods = invoiceCreateDto.getCurrentPeriods();
        LocalDateTime payTime = invoiceCreateDto.getPayTime();

        int addDays = getAddDays(businessType, type, currentPeriods);
        LocalDateTime startTime = DateUtil.getDayStart(DateUtil.plus(payTime, addDays, ChronoUnit.DAYS));
        LocalDateTime endTime = DateUtil.getDayEnd(DateUtil.plus(startTime, 60, ChronoUnit.DAYS));
        int number = getNumber(businessType, type);

        invoiceBean.setValidityStartTime(startTime);
        invoiceBean.setValidityEndTime(endTime);
        invoiceBean.setNumber(number);
        invoiceBean.setStatus(InvoiceStatusEnum.NOT_APPLY.getValue());
        invoiceBean.setIsDelete(IsDeleteEnum.NO.getValue());
    }

    /**
     * 获取天数
     *
     * @param businessType
     * @param type
     * @param currentPeriods
     * @return
     * @throws Exception
     */
    private int getAddDays(Integer businessType, Integer type, Integer currentPeriods) throws Exception {
        if (null == businessType || null == type) {
            return 0;
        }

        int days = 0;
        if (InvoiceBusinessTypeEnum.SUBSCRIBE.getValue() == businessType) {
            if (InvoiceTypeEnum.MAIN_ORDER.getValue() == type) {
                days = 15;
            } else if (InvoiceTypeEnum.REPEAT_ORDER.getValue() == type) {
                days = 15;
            } else if (InvoiceTypeEnum.ADD_MILEAGE.getValue() == type) {
                days = 15;
            } else if (InvoiceTypeEnum.TIME_OUT.getValue() == type) {
                days = 15;
            } else if (InvoiceTypeEnum.BEYOND_MILEAGE.getValue() == type) {
                days = 15;
            } else if (InvoiceTypeEnum.QUALITY_LOSS.getValue() == type) {
                days = 15;
            }
        } else if (InvoiceBusinessTypeEnum.EXCLUSIVEL.getValue() == businessType) {
            if (InvoiceTypeEnum.INSTALLMENT.getValue() == type) {
                days = 30;
            } else if (InvoiceTypeEnum.FULL_PAYMENT.getValue() == type && currentPeriods != null) {
                days = 30 * currentPeriods;
            }
        }

        return days;
    }

    /**
     * 获取张数
     *
     * @param businessType
     * @param type
     * @return
     * @throws Exception
     */
    private int getNumber(Integer businessType, Integer type) throws Exception {
        if (null == businessType || null == type) {
            return 0;
        }

        int number = 0;
        if (InvoiceBusinessTypeEnum.SUBSCRIBE.getValue() == businessType) {
            if (InvoiceTypeEnum.MAIN_ORDER.getValue() == type) {
                number = 2;
            } else if (InvoiceTypeEnum.REPEAT_ORDER.getValue() == type) {
                number = 2;
            } else if (InvoiceTypeEnum.ADD_MILEAGE.getValue() == type) {
                number = 1;
            } else if (InvoiceTypeEnum.TIME_OUT.getValue() == type) {
                number = 1;
            } else if (InvoiceTypeEnum.BEYOND_MILEAGE.getValue() == type) {
                number = 1;
            } else if (InvoiceTypeEnum.QUALITY_LOSS.getValue() == type) {
                number = 1;
            }
        } else if (InvoiceBusinessTypeEnum.EXCLUSIVEL.getValue() == businessType) {
            if (InvoiceTypeEnum.INSTALLMENT.getValue() == type) {
                number = 2;
            } else if (InvoiceTypeEnum.FULL_PAYMENT.getValue() == type) {
                number = 2;
            }
        }

        return number;
    }

    /**
     * 修改发票
     *
     * @param orderCode
     * @return
     * @throws Exception
     */
    @Override
    public Boolean modifyInvoice(Long orderCode) throws Exception {
        List<InvoiceBean> invoiceList = invoiceMapper.getInvoiceByOrder(orderCode);
        if (null == invoiceList || invoiceList.size() < 1) {
            return true;
        }

        List<Integer> idList = new ArrayList<>();
        for (InvoiceBean invoiceBean : invoiceList) {
            Integer id = invoiceBean.getId();
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime validityStartTime = invoiceBean.getValidityStartTime();
            if (now.isBefore(validityStartTime)) {
                idList.add(id);
            }
        }
        int result = invoiceMapper.modifyByIds(idList);
        if (result == idList.size()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 发票列表
     *
     * @param map
     * @param pageNum
     * @param pageSize
     * @return
     * @throws Exception
     */
    @Override
    public Paged<InvoiceDto> getInvoicePage(Map<String, Object> map, Integer pageNum, Integer pageSize) throws Exception {
        long pageCount = invoiceMapper.getPageCount(map);
        if (pageCount < 1) {
            return null;
        }

        List<InvoiceBean> invoiceBeanList = invoiceMapper.getPage(map, pageNum, pageSize);
        List<InvoiceDto> invoiceBeanDtoList = Convert.toInvoiceDtoList(invoiceBeanList);
        return new Paged<InvoiceDto>(invoiceBeanDtoList, pageCount, pageSize);
    }

    /**
     * 根据id获取map集合
     *
     * @param ids
     * @return
     */
    @Override
    public Map<Integer, InvoiceDto> getInvoiceMap(List<Integer> ids) {
        List<InvoiceBean> list = invoiceMapper.getListByIds(ids);
        return Convert.toInvoiceDtoMap(list);
    }

    /**
     * 状态校验
     *
     * @param ids
     * @return
     */
    @Override
    public Boolean getCheckStatusByIds(List<Integer> ids) throws Exception {
        if (null == ids || ids.size() < 1) {
            return false;
        }

        int applyCount = invoiceMapper.getCountByStatus(InvoiceStatusEnum.HAVE_APPLY.getValue(), ids);
        if (applyCount > 0) {
            throw new BizException("存在已申请数据！请重新选择");
        }

        int expiredCount = invoiceMapper.getCountByStatus(InvoiceStatusEnum.HAVE_EXPIRED.getValue(), ids);
        if (expiredCount > 0) {
            throw new BizException("存在已过期数据！请重新选择");
        }
        return true;
    }

    /**
     * 根据id修改状态
     *
     * @param ids
     * @param status
     * @return
     * @throws Exception
     */
    @Override
    public Boolean modifyStatusById(List<Integer> ids, Integer status) throws Exception {
        int result = invoiceMapper.modifyStatusById(ids, status);
        if (result > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 修改发票状态
     *
     * @return
     * @throws Exception
     */
    @Override
    public Boolean modifyStatus() throws Exception {
        invoiceMapper.modifyStatus();
        return true;
    }

    @Override
    public List<InvoiceCreateDto> selectOrderData() {
        return invoiceMapper.selectOrderData();
    }


    @Override
    public List<InvoiceCreateDto> selectSubscribeOrderData() {
        return invoiceMapper.selectSubscribeOrderData();
    }


}
